//
// Created by QU on 24-6-26.
//

/*
C++20中的协程（coroutines）和JavaScript中的单线程Promise并发确实有一些相似之处，但也有关键的不同之处。以下是对两者的详细比较：

相似之处
异步编程模型：

JavaScript：Promise是异步编程的一种方式，它允许你写出看似同步的代码，而实际上是异步执行的。Promise通常用于处理异步操作，例如网络请求、文件读取等。
C++20：协程也是一种异步编程方式，通过co_await关键字，协程可以暂停执行，等到某个条件满足时再继续执行。这允许你编写看似同步的代码，而实际上是异步执行的。
非阻塞：

JavaScript：Promise是非阻塞的，主线程会继续执行，不会被阻塞等待Promise的结果。
C++20：协程也是非阻塞的，当一个协程被co_await暂停时，线程可以继续执行其他任务。
语法简洁：

JavaScript：使用async/await可以使异步代码看起来像同步代码，从而提高代码的可读性。
C++20：协程通过co_await、co_yield和co_return等关键字，使异步代码看起来更简洁和直观。
不同之处
执行环境：

JavaScript：运行在单线程的环境中，所有代码在主线程上执行。JavaScript的事件循环机制使得异步任务能够并发执行，但它们实际上是一个接一个地被处理。
C++20：可以运行在多线程环境中，协程可以在线程池中调度，甚至可以在多核处理器上并行执行。C++协程可以利用多线程的优势，提供更高效的并发执行。
性能：

JavaScript：由于是单线程执行，因此在处理大量计算密集型任务时可能会出现性能瓶颈。
C++20：由于可以在多线程和多核环境中执行，协程在处理计算密集型任务时可以更高效。
实现细节：

JavaScript：Promise是JavaScript语言内建的对象，底层由事件循环驱动。
C++20：协程是一种语言特性，底层实现更加复杂，需要编译器支持。协程通过生成状态机来管理挂起和恢复点，使得在多个挂起点之间切换非常高效。
*/

#include <iostream>
#include <chrono>
#include <thread>
#include <coroutine>

struct Timer {
    std::chrono::milliseconds duration;
    struct Awaiter {
        std::chrono::milliseconds duration;
        bool await_ready() const noexcept {
            std::cout << "Timer: await_ready() called\n";
            return false;
        }
        void await_suspend(std::coroutine_handle<> handle) const {
            std::cout << "Timer: await_suspend() called\n";
            std::thread([handle, duration = this->duration]() {
                std::this_thread::sleep_for(duration);
                std::cout << "Timer: Resuming coroutine after " << duration.count() << " milliseconds\n";
                handle.resume();
            }).detach();
        }
        void await_resume() const noexcept {
            std::cout << "Timer: await_resume() called\n";
        }
    };
    Awaiter operator co_await() const { return Awaiter{duration}; }
};

struct Task {
    struct promise_type {
        Task get_return_object() {
            std::cout << "promise_type: get_return_object() called\n";
            return Task{std::coroutine_handle<promise_type>::from_promise(*this)};
        }
        std::suspend_always initial_suspend() {
            std::cout << "promise_type: initial_suspend() called\n";
            return {};
        }
        std::suspend_always final_suspend() noexcept {
            std::cout << "promise_type: final_suspend() called\n";
            return {};
        }
        void return_void() {
            std::cout << "promise_type: return_void() called\n";
        }
        void unhandled_exception() {
            std::cout << "promise_type: unhandled_exception() called\n";
            std::terminate();
        }
    };

    std::coroutine_handle<promise_type> handle;

    Task(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~Task() {
        if (handle) {
            std::cout << "Task: Destroying coroutine handle\n";
            handle.destroy();
        }
    }
};

Task asyncFunction() {
    std::cout << "asyncFunction: Start\n";
    co_await Timer{std::chrono::milliseconds(1000)};
    std::cout << "asyncFunction: After 1 second\n";
}

int main() {
    std::cout << "main: Starting coroutine\n";
    auto task = asyncFunction();

    // Event loop to ensure coroutine gets a chance to run
    for (int i = 0; i < 20; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        std::this_thread::yield();
    }

    std::cout << "main: Finished waiting\n";
    return 0;
}


/*
代码说明
Task 结构体：
Task 结构体定义了一个协程的返回类型，包括一个嵌套的 promise_type 结构体。
promise_type 包含协程的基本生命周期管理方法，包括 initial_suspend、final_suspend、return_void 和 unhandled_exception。
get_return_object 方法返回一个 Task 实例，该实例持有一个指向 promise_type 的协程句柄。

Timer 结构体：
Timer 结构体用于表示一个等待特定时间的异步操作。
Awaiter 结构体实现了 co_await 机制，包括 await_ready、await_suspend 和 await_resume 方法。

asyncFunction 协程函数：
asyncFunction 是一个返回 Task 类型的协程函数，使用 co_await 关键字等待 Timer 的完成。
asyncFunction 在开始时输出 "Start"，等待 1 秒后输出 "After 1 second"。

main 函数：
main 函数启动 asyncFunction 协程，并等待 2 秒以确保协程有足够的时间完成。

关键点
定义一个返回类型（如 Task）并包含一个 promise_type 结构体。
实现协程的生命周期管理方法，包括 initial_suspend、final_suspend、return_void 和 unhandled_exception。
确保协程函数的返回类型与其 promise_type 结构体相匹配。

在启动协程和等待协程完成后添加了打印语句，以显示主函数的执行过程。
输出示例
运行这段代码，你会看到类似以下的输出：
*/

/*
main: Starting coroutine
promise_type: get_return_object() called
promise_type: initial_suspend() called
asyncFunction: Start
Timer: await_ready() called
Timer: await_suspend() called
Timer: Resuming coroutine after 1000 milliseconds
Timer: await_resume() called
asyncFunction: After 1 second
promise_type: return_void() called
promise_type: final_suspend() called
main: Finished waiting
Task: Destroying coroutine handle
*/

// 通过这些输出，可以更清晰地看到协程的执行流程，包括协程的启动、挂起、恢复以及最终的销毁过程。这有助于理解C++20协程的工作机制。